[PCI] Per-device permissive flag (replaces global permissive flag).
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 28 Jul 2006 11:56:10 +0000 (12:56 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 28 Jul 2006 11:56:10 +0000 (12:56 +0100)
Signed-off-by: Chris Bookholt <hap10@tycho.ncsc.mil>
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c
linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h

index c890001f5417fd93590d7090e296e8706ee08fb2..9eee88cd072162571764ecf57af34636e8415e91 100644 (file)
@@ -15,9 +15,6 @@
 #include "conf_space.h"
 #include "conf_space_quirks.h"
 
-static int permissive = 0;
-module_param(permissive, bool, 0644);
-
 #define DEFINE_PCI_CONFIG(op,size,type)                        \
 int pciback_##op##_config_##size                               \
 (struct pci_dev *dev, int offset, type value, void *data)      \
@@ -258,7 +255,7 @@ int pciback_config_write(struct pci_dev *dev, int offset, int size, u32 value)
                 * This means that some fields may still be read-only because
                 * they have entries in the config_field list that intercept
                 * the write and do nothing. */
-               if (permissive) {
+               if (dev_data->permissive) {
                        switch (size) {
                        case 1:
                                err = pci_write_config_byte(dev, offset,
index ff6db118c02aef6dee3026ecb539c17f3e108eaa..aab9238c2d580f08c1a9ea10a8645fb7be74697e 100644 (file)
@@ -739,6 +739,72 @@ static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf)
 
 DRIVER_ATTR(quirks, S_IRUSR | S_IWUSR, pcistub_quirk_show, pcistub_quirk_add);
 
+static ssize_t permissive_add(struct device_driver *drv, const char *buf,
+                             size_t count)
+{
+       int domain, bus, slot, func;
+       int err;
+       struct pcistub_device *psdev;
+       struct pciback_dev_data *dev_data;
+       err = str_to_slot(buf, &domain, &bus, &slot, &func);
+       if (err)
+               goto out;
+       psdev = pcistub_device_find(domain, bus, slot, func);
+       if (!psdev) {
+               err = -ENODEV;
+               goto out;
+       }
+       if (!psdev->dev) {
+               err = -ENODEV;
+               goto release;
+       }
+       dev_data = pci_get_drvdata(psdev->dev);
+       /* the driver data for a device should never be null at this point */
+       if (!dev_data) {
+               err = -ENXIO;
+               goto release;
+       }
+       if (!dev_data->permissive) {
+               dev_data->permissive = 1;
+               /* Let user know that what they're doing could be unsafe */
+               dev_warn(&psdev->dev->dev,
+                        "enabling permissive mode configuration space accesses!\n");
+               dev_warn(&psdev->dev->dev,
+                        "permissive mode is potentially unsafe!\n");
+       }
+      release:
+       pcistub_device_put(psdev);
+      out:
+       if (!err)
+               err = count;
+       return err;
+}
+
+static ssize_t permissive_show(struct device_driver *drv, char *buf)
+{
+       struct pcistub_device *psdev;
+       struct pciback_dev_data *dev_data;
+       size_t count = 0;
+       unsigned long flags;
+       spin_lock_irqsave(&pcistub_devices_lock, flags);
+       list_for_each_entry(psdev, &pcistub_devices, dev_list) {
+               if (count >= PAGE_SIZE)
+                       break;
+               if (!psdev->dev)
+                       continue;
+               dev_data = pci_get_drvdata(psdev->dev);
+               if (!dev_data || !dev_data->permissive)
+                       continue;
+               count +=
+                   scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
+                             pci_name(psdev->dev));
+       }
+       spin_unlock_irqrestore(&pcistub_devices_lock, flags);
+       return count;
+}
+
+DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add);
+
 static int __init pcistub_init(void)
 {
        int pos = 0;
@@ -784,6 +850,7 @@ static int __init pcistub_init(void)
                           &driver_attr_remove_slot);
        driver_create_file(&pciback_pci_driver.driver, &driver_attr_slots);
        driver_create_file(&pciback_pci_driver.driver, &driver_attr_quirks);
+       driver_create_file(&pciback_pci_driver.driver, &driver_attr_permissive);
 
       out:
        return err;
@@ -834,6 +901,7 @@ static void __exit pciback_cleanup(void)
                           &driver_attr_remove_slot);
        driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots);
        driver_remove_file(&pciback_pci_driver.driver, &driver_attr_quirks);
+       driver_remove_file(&pciback_pci_driver.driver, &driver_attr_permissive);
 
        pci_unregister_driver(&pciback_pci_driver);
 }
index 18c0715b465f63cc7f531dfca5f18da6b2bcc601..4b876e4dd94381c9bd8fff6984faebe717bdc2e8 100644 (file)
@@ -44,6 +44,7 @@ struct pciback_device {
 
 struct pciback_dev_data {
        struct list_head config_fields;
+       int permissive;
        int warned_on_write;
 };